package com.mjk.common.tools.encrypt;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.symmetric.SM4;
import com.mjk.common.tools.logger.BizLogger;

import java.util.Base64;

/**
 * 国密4Demo
 * <p>
 * TODO:
 * 需要的类库，maven管理，或者下载到例如lib目录，右键添加为库
 * com.alibaba/fastjson 1.2.83 https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.83
 * cn.hutool/hutool-core 5.8.6 https://mvnrepository.com/artifact/cn.hutool/hutool-core/5.8.6
 * cn.hutool/hutool-crypto 5.8.6 https://mvnrepository.com/artifact/cn.hutool/hutool-crypto/5.8.6
 * org.bouncycastle/bcprov-jdk15on 1.6.9 https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on/1.69
 *
 * @author oyzh
 * @since 2022/9/16
 */
public class SM4Utils {

    /**
     * 加密，针对sm2签名
     *
     * @param plainStr  待加密字符串
     * @param appId     AppId
     * @param appSecret App密钥
     * @return 已加密字符串
     */
    public static String encryptDataForSM2Sign(String plainStr, String appId, String appSecret) {
        return encryptData(plainStr, true, 2, appId, appSecret);
    }

    /**
     * 加密，针对sm3签名
     *
     * @param plainStr 待加密字符串
     * @return 已加密字符串
     */
    public static String encryptDataForSM3Sign(String plainStr, String appId, String appSecret) {
        return encryptData(plainStr, false, 1, appId, appSecret);
    }

    /**
     * 加密
     *
     * @param plainStr     待加密字符串
     * @param keyUpperCase key是否转大写
     * @param outType      输出类型，1输出urlEncode字符，2输出hex字符
     * @param appId        AppId
     * @param appSecret    App密钥
     * @return 已加密字符串
     */
    public static String encryptData(String plainStr, boolean keyUpperCase, int outType, String appId, String appSecret) {
        String encData = "";
        try {

            String firstKey = appId.substring(0, 16);
            if (keyUpperCase) {
                firstKey = firstKey.toUpperCase();
            }

            SM4 sm4 = new SM4(Mode.ECB.name(), "PKCS7Padding", StrUtil.utf8Bytes(firstKey));
            String encKey = sm4.encryptHex(appSecret);
            if (keyUpperCase) {
                encKey = encKey.toUpperCase();
            }

            String newKey = encKey.substring(0, 16);

            SM4 newSm4 = new SM4(Mode.ECB.name(), "PKCS7Padding", StrUtil.utf8Bytes(newKey));
            if (outType == 1) {
                byte[] encrypt = newSm4.encrypt(plainStr);
                encData = Base64.getUrlEncoder().encodeToString(encrypt);
            } else if (outType == 2) {
                encData = newSm4.encryptHex(plainStr);
            }
            BizLogger.info("加密后密文:" + encData);
        } catch (Exception ex) {
            BizLogger.error(ex);
        }
        return encData;
    }

    /**
     * 解密，针对sm2签名
     *
     * @param encryptStr 密文
     * @param appId      AppId
     * @param appSecret  App密钥
     * @return 已解密字符串
     */
    public static String decryptDataForSM2Sign(String encryptStr, String appId, String appSecret) {
        return decryptData(encryptStr, true, appId, appSecret);
    }

    /**
     * 解密，针对sm3签名
     *
     * @param encryptStr 密文
     * @param appId      AppId
     * @param appSecret  App密钥
     * @return 已解密字符串
     */
    public static String decryptDataForSM3Sign(String encryptStr, String appId, String appSecret) {
        return decryptData(encryptStr, false, appId, appSecret);
    }

    /**
     * 解密
     *
     * @param encryptStr   密文
     * @param keyUpperCase key是否转大写
     * @param appId        AppId
     * @param appSecret    App密钥
     * @return 已解密字符串
     */
    public static String decryptData(String encryptStr, boolean keyUpperCase, String appId, String appSecret) {
        try {

            String firstKey = appId.substring(0, 16);
            if (keyUpperCase) {
                firstKey = firstKey.toUpperCase();
            }
            SM4 sm4 = new SM4(Mode.ECB.name(), "PKCS7Padding", StrUtil.utf8Bytes(firstKey));
            String encKey = sm4.encryptHex(appSecret);
            if (keyUpperCase) {
                encKey = encKey.toUpperCase();
            }
            String newKey = encKey.substring(0, 16);
            SM4 newSm4 = new SM4(Mode.ECB.name(), "PKCS7Padding", StrUtil.utf8Bytes(newKey));
            String decryptData = newSm4.decryptStr(encryptStr);
            System.out.println("解密后密文:" + decryptData);
            return decryptData;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "";
    }


    public static void main(String[] args) {
        SM4Utils demo = new SM4Utils();
    }
}

